﻿using System;
using System.Windows;
using System.Windows.Interactivity;
using Expression.Samples.Physics;

namespace Expression.Samples.Physics.Behaviors {
	
	public class CollideTrigger: TriggerBase<FrameworkElement> {

		private Entity entity;

		public static readonly DependencyProperty TypeProperty = DependencyProperty.Register("Type", typeof(Type), typeof(CollideTrigger), new PropertyMetadata(null));
		public static readonly DependencyProperty MinForceProperty = DependencyProperty.Register("MinForce", typeof(double), typeof(CollideTrigger), new PropertyMetadata(0.0));

		public double MinForce {
			get { return (double)this.GetValue(CollideTrigger.MinForceProperty); }
			set { this.SetValue(CollideTrigger.MinForceProperty, value); }
		}


		public Type Type {
			get { return (Type)this.GetValue(CollideTrigger.TypeProperty); }
			set { this.SetValue(CollideTrigger.TypeProperty, value); }
		}

		protected override void  OnAttached()
		{
 			base.OnAttached();

			this.entity = this.GetEntity(this.AssociatedObject);

			if (this.entity == null) {
				this.Dispatcher.BeginInvoke(delegate {
					this.entity = this.GetEntity(this.AssociatedObject);
					this.Attach(this.entity);
				});
			}
			else
				this.Attach(this.entity);
		}

		protected override void OnDetaching() {
			base.OnDetaching();

			if (this.entity != null)
				this.Detach(entity);

		}

		private Entity GetEntity(FrameworkElement element) {
			return Entity.GetElementEntity(element);
		}

		private void Attach(Entity entity) {
			entity.Collide += this.HandleCollide;
		}

		private void Detach(Entity entity) {
			entity.Collide -= this.HandleCollide;
		}

		private void HandleCollide(object sender, CollideEventArgs e) {
			if (e.ContactPoint.Velocity.Length() > this.MinForce) {
				if (this.Type == null || this.Type.IsAssignableFrom(e.Other.GetType()))
					this.InvokeActions(e);

			}
		}
	}
}
